package com.yy.ttmodule.activity;


import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.telephony.PhoneStateListener;
import android.telephony.SignalStrength;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;

import com.android.test.jnidemo.JniText;
import com.yy.ttmodule.cardStatus.BmChecker;
import com.yy.ttmodule.cardStatus.StatusBean;
import com.yy.ttmodule.control.Constant;
import com.yy.ttmodule.control.ParamCons;
import com.yy.ttmodule.control.ParseParam;
import com.yy.ttmodule.manager.ControlManager;
import com.yy.ttmodule.receiver.ConnectionChangeReceiver;
import com.yy.ttmodule.telephony.TelephonyUtil;
import com.yy.ttmodule.udp.ConvertData;
import com.yy.ttmodule.udp.DataTypeConversion;
import com.yy.ttmodule.udp.RxDataCallBack;
import com.yy.ttmodule.utils.DataQos;
import com.yy.ttmodule.utils.GPSLocationManager;
import com.yy.ttmodule.utils.Logger;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

public class BaseActivity extends Activity implements RxDataCallBack {

    private final String TAG = "BaseActivity";

    protected CmdHandler mCmdHandler;
    private Message msg;
    private final int MSG_PKG_DATA = 0x01;

    TelephonyManager mTelephonyManager;
    int dbm = 99;

    ConnectionChangeReceiver mConnectionChangeReceiver;
    Context mContext;

    SmsReceiver mSmsReceiver;

    protected ConcurrentHashMap<String, StatusBean> mMap = new ConcurrentHashMap<String, StatusBean>();
    protected volatile BmChecker mBmCFChecker;
    protected volatile BmChecker mBmBarChecker;

    private Handler mHandler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;

        mCmdHandler = new CmdHandler(Looper.getMainLooper(), this);
        mTelephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
        PhoneStateListener signalStateListener = new PhoneStateListener() {
            @Override
            public void onSignalStrengthsChanged(SignalStrength signalStrength) {
                super.onSignalStrengthsChanged(signalStrength);
                //通过反射获取当前信号值
                try {///https://blog.csdn.net/sinat_31057219/article/details/81134030
                    //https://blog.csdn.net/liulilittle/article/details/125187129 窝蜂移动数据网络状态
//                    int gsmSignalStrength = signalStrength.getGsmSignalStrength();
//                    int dbm = -113 + 2 * gsmSignalStrength;

                    Method method = signalStrength.getClass().getMethod("getDbm");
                    dbm = (int) method.invoke(signalStrength);
                    Logger.d("dbm : " + getDbmLevel(dbm));
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
//                myText.setText("CDMA RSSI = "+ String.valueOf(signalStrength.getCdmaDbm()));
//                myText1.setText("GSM Cinr = "+ String.valueOf(signalStrength.getGsmSignalStrength()));
            }
        };
        mTelephonyManager.listen(signalStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);

        ControlManager.getInstance().init();
        ControlManager.getInstance().regRxDataCallBack(this);

//        ControlManager.getInstance().ackReceiveSmsRes("13756897856",
//                "sadc阿斯蒂芬就萨迪克按实际蛋壳看");

        mConnectionChangeReceiver = new ConnectionChangeReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        registerReceiver(mConnectionChangeReceiver, intentFilter);

        IntentFilter intentFilter1 = new IntentFilter();
        intentFilter1.addAction(SENT_SMS_ACTION);
        intentFilter1.addAction(DELIVERED_SMS_ACTION);
        registerReceiver(sendMessageReceiver, intentFilter1);

        mSmsReceiver = new SmsReceiver();
        IntentFilter intentFilter2 = new IntentFilter();
        intentFilter2.addAction(SmsReceiver.SMS_RECEIVED_ACTION);
        registerReceiver(mSmsReceiver, intentFilter2);

        mTelephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);

        //rebootSystem();
    }

    @Override
    public void onData(byte[] data, int len) {
        sendMsg(MSG_PKG_DATA, data, len);
    }

    private int getDbmLevel(int dbm) {
        int level = 0;
        if (dbm <= -113) {
            level = 0;
        } else if (-113 < dbm && dbm < -111) {
            level = 1;
        } else if (-111 <= dbm && dbm < -51) {
            level = (int) Math.abs( (dbm + 111.0) / (( -51 + 111.0 ) / 29) + 2.0 );
        } else if (dbm >= -51) {
            level = 31;
        }
        if ( dbm == 99 ) {
            level = dbm;
        }
        return level;
    }

    public int getNetworkState(Context context) {
        ConnectivityManager connManager =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); // 获取网络服务
        if (null == connManager) { // 为空则认为无网络
            return Constant.NETWORK_NONE;
        }
        // 获取网络类型，如果为空，返回无网络
        NetworkInfo activeNetInfo = connManager.getActiveNetworkInfo();
        if (activeNetInfo == null || !activeNetInfo.isAvailable()) {
            return Constant.NETWORK_NONE;
        }
        // 若不是WIFI，则去判断是2G、3G、4G网
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        int networkType = telephonyManager.getNetworkType();
        switch (networkType) {
            // 4G网络
            case TelephonyManager.NETWORK_TYPE_LTE:
                return Constant.NETWORK_4G;
        }

        return Constant.NETWORK_NONE;
    }

    public static int getAirMode(Context context) {
        return (Settings.System.getInt(context.getContentResolver(),
                Settings.System.AIRPLANE_MODE_ON, 0) == 1 ?
                Constant.AIRPLANE_MODE_ON : Constant.AIRPLANE_MODE_OFF);
    }

    public static void setAirMode(Context context, int mode) {
        Settings.System.putInt(context.getContentResolver(),
                Settings.System.AIRPLANE_MODE_ON, mode == Constant.AIRPLANE_MODE_ON ? 1 : 0);
    }

    public boolean getMobileDataState() {
        try {
            TelephonyManager telephonyService =
                    (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
            Method getDataEnabled = telephonyService.getClass().getDeclaredMethod("getDataEnabled");
            if (null != getDataEnabled) {
                return (Boolean) getDataEnabled.invoke(telephonyService);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public void setMobileDataEnabled(boolean enabled) {
        ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
//        cm.setMobileDataEnabled(enabled);
        try {
            Field field = Class.forName(ConnectivityManager.class.getName())
                    .getDeclaredField("mService");
            field.setAccessible(true);
            // get Object of mService
            Object obj = field.get(cm);// connectivitymanager.mService
            // get IConnectivityManager class
            Class myClass = Class.forName(obj.getClass().getName());
            Method method = myClass.getDeclaredMethod("setMobileDataEnabled",
                    boolean.class);
            method.setAccessible(true);
            method.invoke(obj, enabled);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }//https://www.jianshu.com/p/cda763517590
    }

    public void handleCmdMsg(Message msg) {
        byte data[] = (byte[]) msg.obj;
        int frameType = resolveDate(data,
                ParseParam.FRAME_TYPE_ID, ParseParam.FRAME_TYPE_LEN);

        try {
            switch ( (byte) (frameType & 0xFF) ) {
                case ParamCons.CMD_NETWORK_ACCESS_STATUS://4.1入网状态
                    //dumpsys telephony.registry
                    ControlManager.getInstance().ackNetAccessStatus(getNetworkState(this));
                    break;
                case ParamCons.CMD_SIGNAL_STRENGTH_QUERY://4.2信号强度
                    ControlManager.getInstance().ackSignalStrength(
                            getDbmLevel(dbm));
                    break;
                case ParamCons.CMD_DATA_STATUS_QUERY://4.3数据状态
                    int psVal = Constant.DATA_PS_OFF;
                    if ( getMobileDataState() ) {
                        String Qosdata[]= DataQos.readFileData(mContext)
                                .replace('\n', ' ')
                                .replace('\r', ' ')
                                .replace('\0', ' ').split(" ");
                        if (Qosdata.length != 4) {
                            Logger.v(TAG, "onCreate data[] invalid");
                            psVal = Constant.DATA_PS_OFF;
                        } else {
                            psVal = Constant.getQos2PsValue(mContext, Integer.parseInt(Qosdata[2]));
                        }
                    }
                    ControlManager.getInstance().ackDataStatus(psVal);
                    break;
                case ParamCons.CMD_DATA_STATUS_SET:
                    try {
                        setMobileDataEnabled(false);
                        int psFrame = data[ParseParam.FRAME_VALUE_ID] & 0x0FF;
                        int dos = Constant.getPs2QosValue(mContext, psFrame);
                        if ( dos > 0 ) {
                            DataQos.writeData("1" + " 4 " + dos + " " + dos);
                        }
                        setMobileDataEnabled(true);
    //                mTelephonyManager.setPreferredNetworkType(TelephonyManager.NETWORK_TYPE_GSM);
    //                mTelephonyManager.setPreferredNetworkType(TelephonyManager.NETWORK_TYPE_UMTS);
                        ControlManager.getInstance().ackDataStatusSetRes(Constant.EXC_SUCCEED);
                    } catch (Exception e) {
                        e.printStackTrace();
                        ControlManager.getInstance().ackDataStatusSetRes(Constant.EXC_FAILURE);
                    }
                    break;
                case ParamCons.CMD_FLIGHT_MODE_QUERY:
                    ControlManager.getInstance().ackFlightMode(getAirMode(this));
                    break;
                case ParamCons.CMD_FLIGHT_MODE_SET:
                    try {
                        //https://www.idcnote.com/php/biji/86623.html
                        setAirMode(this, resolveDate(data,
                                ParseParam.FRAME_VALUE_ID, ParseParam.FRAME_VALUE_LEN));
                        ControlManager.getInstance().ackFlightModeSet(Constant.EXC_SUCCEED);
                    } catch (Exception e) {
                        ControlManager.getInstance().ackFlightModeSet(Constant.EXC_FAILURE);
                    }
                    break;
                case ParamCons.CMD_LOCAL_PHONE_NUMBER_INQUIRY:
                    String num = mTelephonyManager.getLine1Number();
                    if ( num != null && !num.isEmpty() ) {
                        ControlManager.getInstance().ackPhoneNum(
                                mTelephonyManager.getLine1Number());
                    }
                    break;
                case ParamCons.CMD_CARD_STATUS_INQUIRY:
                    int mCard = mMap.get(StatusBean.KEY_CF_CARD).getStatus() != StatusBean.STATUS_OK ?
                            Constant.CARD_ABNOR : Constant.CARD_NOR;
                    int mBar = mMap.get(StatusBean.KEY_BM_BAR).getStatus() != StatusBean.STATUS_OK ?
                            Constant.CARD_ABNOR : Constant.CARD_NOR;
                    ControlManager.getInstance().ackCardStatus(mCard, mBar);
                    break;
                case ParamCons.CMD_DIAL:
                    //ACTION_NEW_OUTGOING_CALL //这个地方只有你拨号的瞬间会调用
                    int numLen = resolveDate(data,
                            ParseParam.FRAME_LEN_ID, ParseParam.FRAME_LEN_LEN);
                    byte[] dailNum = ConvertData.subBytes(data, ParseParam.FRAME_VALUE_ID, numLen);
                    String strphone = new String(dailNum, StandardCharsets.US_ASCII);

                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_CALL);
                    intent.setData(Uri.parse("tel:" + strphone));
                    startActivity(intent);
                    ControlManager.getInstance().ackDialRes(Constant.EXC_SUCCEED);
                    break;
                case ParamCons.CMD_ANSWER:
                    TelephonyUtil.answerRingingCall(this);
                    ControlManager.getInstance().ackAnswerRes(Constant.EXC_SUCCEED);
                    Log.d(TAG,"CMD_ANSWER,ret :" + JniText.tianTongAudioStartMode(0));
                    break;
                case ParamCons.CMD_HANG_UP:
                    TelephonyUtil.killCall(this);
                    ControlManager.getInstance().ackHangUpRes(Constant.EXC_SUCCEED);
                    Log.d(TAG,"CMD_HANG_UP,ret :" + JniText.tianTongAudioStop());
                    break;
                case ParamCons.CMD_CALL_STATUS_INQUIRY:
                    int callstatus = mTelephonyManager.getCallState();
                    if ( callstatus == TelephonyManager.CALL_STATE_IDLE ) {
                        ControlManager.getInstance().ackCallStatus(Constant.CALL_STATE_IDLE);
                    } else if ( callstatus == TelephonyManager.CALL_STATE_RINGING ) {
                        ControlManager.getInstance().ackCallStatus(Constant.CALL_STATE_RINGING);
                    } else if ( callstatus == TelephonyManager.CALL_STATE_OFFHOOK ) {
                        ControlManager.getInstance().ackCallStatus(Constant.CALL_STATE_OFFHOOK);
                    }
                    break;
                case ParamCons.CMD_UPLINK_PCM_SENDS_DATA:
                    int len = resolveDate(data,
                            ParseParam.FRAME_LEN_ID, ParseParam.FRAME_LEN_LEN);
                    byte[] pcmData = ConvertData.subBytes(data, ParseParam.FRAME_VALUE_ID, len);
                    mHandler.postDelayed(()->{
                        int res = JniText.tianTongAudioBFromPc(pcmData,  pcmData.length);
                        Log.d(TAG,"tianTongAudioBFromPc ret :" + res);
                    }, 16);
                    break;
                case ParamCons.CMD_SEND_TEXT_MESSAGE:
                    try {
                        int valLen = resolveDate(data,
                                ParseParam.FRAME_LEN_ID, ParseParam.FRAME_LEN_LEN);
                        String strNumber = new String(
                                ConvertData.subBytes(data, ParseParam.FRAME_VALUE_ID, Constant.PHONE_NUM_LEN),
                                StandardCharsets.US_ASCII);
                        String smsText = new String(
                                ConvertData.subBytes(data, ParseParam.FRAME_VALUE_ID + Constant.PHONE_NUM_LEN,
                                        valLen - Constant.PHONE_NUM_LEN), "GBK");

                        sendSMS(strNumber, smsText);
                        /*SmsManager smsManager = SmsManager.getDefault();
                        smsManager.sendTextMessage(strNumber, null, smsText, null, null);*/
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    break;
                case ParamCons.CMD_REBOOT:
                    rebootSystem();
                    ControlManager.getInstance().ackRebootRes(Constant.EXC_SUCCEED);
                    break;
                case ParamCons.CMD_BEIDOU_NAV_QUERY:
                    ControlManager.getInstance().ackBeidouNavRes(
                            GPSLocationManager.getInstances(null).getGpsData());
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //https://www.cnblogs.com/jamiechoo/articles/16192531.html 新建类
    //https://blog.51cto.com/u_16213436/7566651 广播形式
    PhoneStateListener phoneStateListener = new PhoneStateListener() {
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
            switch (state) {
                //https://www.jianshu.com/p/b1f5b9d85d6d
                case TelephonyManager.CALL_STATE_IDLE: // 无通话
                    //不管是去电还是来电通话结束都会调用，不管是不是你挂的
                    Log.d(TAG, "No call in progress");
                    break;
                case TelephonyManager.CALL_STATE_RINGING: // 有电话进入铃音但未接听
                    //如果是来电，这个必须点击接听按钮才会调用
                    //如果是拨打，那么一开始就会调用，并不是打通了之后才会调用
                    Log.d(TAG, "Incoming call from number: " + incomingNumber);
                    ControlManager.getInstance().ackCallStatus(Constant.CALL_STATE_INCOMING);
                    ControlManager.getInstance().ackIncomingCall(incomingNumber);
                    break;
                case TelephonyManager.CALL_STATE_OFFHOOK: // 正在通话或等待接听
                    //只有来电的时候会调用
                    Log.d(TAG, "Active or waiting for an active call");
                    break;
            }
        }
    };

    //https://blog.csdn.net/qq_37599041/article/details/129319220
    public class SmsReceiver extends BroadcastReceiver {

        public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
        public static final String SMS_DELIVER_ACTION = "android.provider.Telephony.SMS_DELIVER";

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (SMS_RECEIVED_ACTION.equals(action) || SMS_DELIVER_ACTION.equals(action) ) {
                Bundle bundle = intent.getExtras();
                if (bundle != null) {
                    Object[] pdus = (Object[]) bundle.get("pdus");
                    if (pdus != null && pdus.length > 0) {
                        SmsMessage[] messages = new SmsMessage[pdus.length];
                        for (int i = 0; i < pdus.length; i++) {
                            byte[] pdu = (byte[]) pdus[i];
                            messages[i] = SmsMessage.createFromPdu(pdu);
                        }
                        for (SmsMessage message : messages) {
                            String content = message.getMessageBody();// 得到短信内容
                            String sender = message.getOriginatingAddress();// 得到发信息的号码
                            ControlManager.getInstance().ackReceiveSmsRes(sender, content);
                        }
                    }
                }
            }
        }
    }

    //https://codeleading.com/article/19125665175/
    String SENT_SMS_ACTION = "SENT_SMS_ACTION";
    String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION";

    private BroadcastReceiver sendMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "send。。" + intent.getAction() + "---" + getResultCode() + "---" + getResultData());
            if ( intent.getAction() != null && intent.getAction().equals(DELIVERED_SMS_ACTION)) {
                Log.i(TAG, "receiver。。" + intent.getAction() + "---" + getResultCode() + "---" + getResultData());
                //表示对方成功收到短信
                Toast.makeText(mContext, "对方接收成功", Toast.LENGTH_LONG).show();
            } else {
                //判断短信是否发送成功
                switch (getResultCode()) {
                    case Activity.RESULT_OK:
                        Toast.makeText(context, "短信发送成功", Toast.LENGTH_SHORT).show();
                        ControlManager.getInstance().ackSendSmsRes(Constant.EXC_SUCCEED);
                        break;
                    default:
                        Toast.makeText(mContext, "发送失败", Toast.LENGTH_LONG).show();
                        ControlManager.getInstance().ackSendSmsRes(Constant.EXC_FAILURE);
                        break;
                }
            }
        }
    };

    /**
     * 参数说明
     * destinationAddress:收信人的手机号码
     * scAddress:发信人的手机号码
     * text:发送信息的内容
     * sentIntent:发送是否成功的回执，用于监听短信是否发送成功。
     * DeliveryIntent:接收是否成功的回执，用于监听短信对方是否接收成功。
     */
    private void sendSMS(String phoneNumber, String message) {
        // ---sends an SMS message to another device---
        SmsManager sms = SmsManager.getDefault();

        // create the sentIntent parameter
        Intent sentIntent = new Intent(SENT_SMS_ACTION);
        PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, sentIntent, 0);

        // create the deilverIntent parameter
        Intent deliverIntent = new Intent(DELIVERED_SMS_ACTION);
        PendingIntent deliverPI = PendingIntent.getBroadcast(this, 0, deliverIntent, 0);

        //如果短信内容超过70个字符 将这条短信拆成多条短信发送出去
        if (message.length() > 70) {
            ArrayList<String> msgs = sms.divideMessage(message);
            for (String msg : msgs) {
                sms.sendTextMessage(phoneNumber, null, msg, sentPI, deliverPI);
            }
        } else {
            sms.sendTextMessage(phoneNumber, null, message, sentPI, deliverPI);
        }
    }

    private void rebootSystem() {
        Intent intent = new Intent(Intent.ACTION_REBOOT);
        intent.putExtra("nowait", 1);
        intent.putExtra("interval", 1);
        intent.putExtra("window", 0);
        sendBroadcast(intent);
        /*Process process = null;
        try {
            process = Runtime.getRuntime().exec("su");
            DataOutputStream outputStream = new DataOutputStream(process.getOutputStream());
            outputStream.writeBytes("/system/bin/reboot\n");
            outputStream.flush();
            outputStream.writeBytes("exit\n");
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }*/
    }
    //Android-系统服务-TelephonyManager
    //https://blog.csdn.net/pwp032984/article/details/122633590

    @Override
    public void onDestroy() {
        unregisterReceiver(mConnectionChangeReceiver);
        unregisterReceiver(sendMessageReceiver);
        unregisterReceiver(mSmsReceiver);
        ControlManager.getInstance().destory();
        super.onDestroy();
    }

    protected void sendMsg(int what, Object obj, int arg) {
        msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg;
        mCmdHandler.sendMessage(msg);
    }

    int resolveDate(byte[] date, int offSet, int len) {
        int result = 0;
        if (len == 2) {
            result = DataTypeConversion.bytesToShortLiterEnd(date, offSet);
        } else if (len == 1) {
            result = DataTypeConversion.byteToInt(date[offSet]);
        }
        return result;
    }

}
